﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc.Html;
using System.Web.Mvc;
using System.Reflection;
using System.Linq.Expressions;
using Spotless.Services;

namespace SpotlessWeb.Helpers
{    
    public static class FilterHelpers
    {
        private static string DefaultFilterKey = "filter";

        private static bool HasValue(this string source)
        {
            return !string.IsNullOrEmpty(source);
        }

        private static bool HasNoValue(this string source)
        {
            return !source.HasValue();
        }

        public static string GetFilterKey(this ViewDataDictionary viewData, IFilterExpression expression)
        {
            return viewData.GetFilterKey(expression, null);
        }

        public static string GetFilterKey(this ViewDataDictionary viewData, IFilterExpression expression, string key)
        {
            return (key.HasValue() ? key : DefaultFilterKey) + "." + expression.ToString();
        }


        public static Dictionary<FilterExpressionInfo, IFilterExpression> GetFilters(this ViewDataDictionary viewData)
        {
            return viewData.GetFilters((string)null);
        }
        
        public static Dictionary<FilterExpressionInfo, IFilterExpression> GetFilters(this ViewDataDictionary viewData, string key)
        {
            return viewData[key.HasValue() ? key : DefaultFilterKey] as Dictionary<FilterExpressionInfo, IFilterExpression>;
        }

        public static void SetFilters<TModel>(this ViewDataDictionary viewData, Dictionary<FilterExpressionInfo, FilterExpression<TModel>> filters)
            where TModel : class
        {
            viewData.SetFilters(filters, (string)null);
        }

        public static void SetFilters<TModel>(this ViewDataDictionary viewData, Dictionary<FilterExpressionInfo, FilterExpression<TModel>> filters, string key)
        where TModel : class
        {
            viewData[key.HasValue() ? key : DefaultFilterKey] = filters.ToDictionary(x => x.Key, y => (IFilterExpression)y.Value);
        }
        public static MvcForm BeginFilterForm(this HtmlHelper html)
        {
            return html.BeginForm((string)null, (string)null, FormMethod.Get);
        }

        public static MvcHtmlString FilterInput(this HtmlHelper html, string formKey, SpotlessWeb.Helpers.FilterExpressionInfo info, Spotless.Services.IFilterExpression filter)
        {
            string key = formKey + "." + info.DisplayName.Replace(" ", "").ToString();
            var val = html.ViewContext.HttpContext.Request[key];
            switch (info.Type)
            {
                case FilterExpressionInfo.FieldTypes.TextBox:
                    return html.TextBox(key, val, info.HtmlAttributes);
                case FilterExpressionInfo.FieldTypes.DropDown:
                    var itemsToUse = info.SelectList().Select(x => new SelectListItem() { Text = x.Text, Value = x.Value, Selected = x.Value.Equals(val, StringComparison.CurrentCultureIgnoreCase) }).ToArray();
                    return html.DropDownList(key, itemsToUse, "All", info.HtmlAttributes);
                default:
                    throw new NotImplementedException(string.Format("Filter Type {0} not implimented", info.Type.ToString()));
            }
        }

        /*public static MvcHtmlString FilterTextBoxFor(this HtmlHelper html, Spotless.Services.IFilterExpression filter)
        {
            return html.FilterTextBoxFor(filter, null);
        }

        public static MvcHtmlString FilterTextBoxFor(this HtmlHelper html, Spotless.Services.IFilterExpression filter, object htmlAttributes)
        {
            var key = "filter." + filter.ToString();
            var val = html.ViewContext.HttpContext.Request[key];
            return html.TextBox(key, val, htmlAttributes);
        }

        public static MvcHtmlString FilterDropDownFor(this HtmlHelper html, Spotless.Services.IFilterExpression filter, IEnumerable<SelectListItem> items)
        {
            return html.FilterDropDownFor(filter, items, null);
        }

        public static MvcHtmlString FilterDropDownFor(this HtmlHelper html, Spotless.Services.IFilterExpression filter, IEnumerable<SelectListItem> items, object htmlAttributes)
        {
            var key = "filter." + filter.ToString();
            var val = html.ViewContext.HttpContext.Request[key];
            var itemsToUse = items.Select(x => new SelectListItem() { Text = x.Text, Value = x.Value, Selected = x.Value.Equals(val, StringComparison.CurrentCultureIgnoreCase) }).ToArray();
            return html.DropDownList(key, itemsToUse, "All", htmlAttributes);
        }*/
    }

    public class FilterExpressionInfo
    {
        /*public FilterExpressionInfo(string displayName, FieldTypes fieldType)
            : this(displayName, fieldType, null)
        {
        }*/

        private FilterExpressionInfo(string displayName, FieldTypes fieldType, object htmlAttributes)
        {
            this.DisplayName = displayName;
            this.Type = fieldType;
            this.HtmlAttributes = htmlAttributes;
        }

        public string DisplayName { get; private set; }
        public FieldTypes Type { get; private set; }
        public object HtmlAttributes { get; private set; }

        private IEnumerable<SelectListItem> SelectListData;
        private void SetSelectListData(IEnumerable<SelectListItem> data)
        {
            this.SelectListData = data;
        }
        public IEnumerable<SelectListItem> SelectList()
        {
            return this.SelectListData;
        }

        public enum FieldTypes { TextBox, DropDown }

        public static FilterExpressionInfo TextBox(string displayName)
        {
            return TextBox(displayName, null);
        }

        public static FilterExpressionInfo TextBox(string displayName, object htmlAttributes)
        {
            return new FilterExpressionInfo(displayName, FieldTypes.TextBox, htmlAttributes);
        }

        public static FilterExpressionInfo DropDown(string displayName, IEnumerable<SelectListItem> data)
        {
            return DropDown(displayName, data, null);
        }

        public static FilterExpressionInfo DropDown(string displayName, IEnumerable<SelectListItem> data, object html)
        {
            var tmp = new FilterExpressionInfo(displayName, FieldTypes.DropDown, html);
            tmp.SetSelectListData(data);
            return tmp;
        }
    }
}
